class PoemScene extends eui.Component {
    private poemChars: Array<object>;
    private poemCharNum: number;
    private uuidMap: object;
    private score: number;
    private dragging: boolean;
    private textScoreHandler: egret.TextField;
    private readonly index: number;
    private stageW: number;
    private stageH: number;
    private poemList: Array<Poem>;
    private readonly scoreBoardFromY: number = 60;
    private readonly scoreBoardH: number = 80;
    private readonly titleMarginTop: number = 20;
    private titleH: number;
    private titleRealW: number;
    private titleFromX: number;
    private readonly authorBoardMarginTop: number = 20;
    private readonly authorBoardH: number = 40;
    private readonly bodyMarginTop: number = 20;
    private readonly bodyMarginBottom: number = 100;

    public constructor(i: number) {
        super();
        this.skinName = "PoemSceneSkin";
        this.index = i;
        this.addEventListener(egret.Event.ADDED_TO_STAGE, this.addToStage, this);
        this.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.touchBegin, this);
        this.addEventListener(egret.TouchEvent.TOUCH_END, this.touchEnd, this);
        this.addEventListener(egret.TouchEvent.TOUCH_RELEASE_OUTSIDE, this.touchEnd, this);
    }

    private addToStage() {
        const {ctx} = Director.getInstance();
        this.stageW = this.stage.stageWidth;
        this.stageH = this.stage.stageHeight;
        this.poemList = ctx['poemList'];
        this.renderPoem(this.index || 0);
    }

    protected renderPoem(i) {
        const {stageW, stageH, poemList} = this;

        const bg = new egret.Shape();
        bg.graphics.beginFill(ColorYunShuiLan, 0.3);
        bg.graphics.drawRect(0, 0, stageW, stageH);
        bg.graphics.endFill();
        this.addChild(bg);

        loadImgToScene(this, "bg02_01_png", {
            mode: 'fitW_alignLB',
            stageWidth: stageW,
            stageHeight: stageH,
        });

        loadImgToScene(this, "bg02_02_png", {
            mode: 'fitW_alignLT',
            stageWidth: stageW,
        });

        const rw = 50;
        const rh = 50;
        const poemMap = poemList[i];
        let {poemChars} = this;
        poemChars = [];

        const markBox = new egret.Shape();
        markBox.graphics.beginFill(ColorBlack, 0.1);
        const shapeW = stageW - SizePw;
        const shapeH = stageH - SizePh;
        markBox.graphics.drawRoundRect(SizePw / 2, SizePh / 2, shapeW, shapeH, rw, rh);
        markBox.graphics.endFill();
        this.addChild(markBox);
        this.score = 0;
        if (poemMap) {
            const {title, content} = poemMap;
            const rowBoxW = stageW - SizePw * 4;
            const titOpt = {
                title,
                size: 64,
                boxW: rowBoxW
            };
            const titHandle = this.drawTitle(titOpt);
            let bodyCharBoxW = 50;
            let bodyCharBoxH = 50;
            let bodyCharSize = 36;
            const bodyCharPw = 20;
            const bodyCharPh = 20;
            let cnt = 0;
            const poemBodyCharIndexArr = [];
            let poemBodyCharFromIndex = poemChars.length;

            let rowCharMaxLen = 0;
            content.map((row) => {
                const bodyChars = row.split('');
                const bodyCharLen = bodyChars.length;
                if (bodyCharLen > rowCharMaxLen) {
                    rowCharMaxLen = bodyCharLen;
                }
            });

            if (rowCharMaxLen) {
                const bw = (stageW - SizePw * 4 - (rowCharMaxLen - 1) * bodyCharPw) / rowCharMaxLen;
                bodyCharBoxW = bw;
                bodyCharBoxH = bw;
                bodyCharSize = Math.floor(bw * 0.8);
            }

            const poemRowNum = content.length;
            const bodyH = poemRowNum * (bodyCharBoxH + bodyCharPh);

            const {
                titleH,
                titleMarginTop,
                authorBoardMarginTop,
                authorBoardH,
                bodyMarginTop,
                scoreBoardFromY,
                scoreBoardH,
                bodyMarginBottom
            } = this;
            const midH = titleH + authorBoardMarginTop + authorBoardH + bodyMarginTop;
            const poemBoxTotalH = midH + bodyH;
            let titleFromY = scoreBoardFromY + scoreBoardH + titleMarginTop;
            const poemBoxSpaceH = stageH - (titleFromY + bodyMarginBottom);
            let bodyFromY = titleFromY + midH;

            if (poemBoxSpaceH >= poemBoxTotalH) {
                titleFromY = titleFromY + (poemBoxSpaceH - poemBoxTotalH) * 0.33;
                bodyFromY = titleFromY + midH;
            } else {
                const bh = Math.floor((poemBoxSpaceH - midH - poemRowNum * bodyCharPw) / poemRowNum);
                bodyCharBoxW = bh;
                bodyCharBoxH = bh;
                bodyCharSize = Math.floor(bh * 0.8);
            }

            const titBoxHandle = new egret.Shape();
            titBoxHandle.graphics.beginFill(ColorWhite, 0.3);
            const titBoxFromX = (stageW - this.titleRealW - SizePw) / 2;
            titBoxHandle.graphics.drawRoundRect(titBoxFromX, titleFromY - SizePh / 2, this.titleRealW + SizePw, this.titleH + SizePh, 10, 10);
            titBoxHandle.graphics.endFill();
            this.addChildAt(titBoxHandle, this.numChildren);
            titHandle.y = titleFromY;
            this.addChildAt(titHandle, this.numChildren);

            content.map((row, i) => {
                const bodyChars = row.split('');
                const bodyCharLen = bodyChars.length;
                const bodyRowW = bodyCharBoxW * bodyCharLen + bodyCharPw * (bodyCharLen - 1);
                const bodyRowFromX = (stageW - bodyRowW) / 2;
                const bodyRowFromY = bodyFromY + bodyCharPh + (bodyCharBoxH + bodyCharPh) * i;
                bodyChars.map((char, n) => {
                    const isSymbol = isSymbolChar(char);
                    const offsetX = (bodyCharPw + bodyCharBoxW) * n;
                    const x = bodyRowFromX + offsetX + bodyCharBoxW / 2;
                    const y = bodyRowFromY + bodyCharBoxH / 2;
                    const boxX = bodyRowFromX + offsetX;
                    const boxY = bodyRowFromY;
                    const boxW = bodyCharBoxW;
                    const boxH = bodyCharBoxH;
                    const boxBorderRadius = 8;
                    const uuid = randomString(16);
                    const options = {
                        i: cnt,
                        uuid,
                        home: char,
                        char,
                        x,
                        y,
                        boxX,
                        boxY,
                        boxW,
                        boxH,
                        size: bodyCharSize,
                        boxBorderRadius,
                        symbol: isSymbol
                    };
                    poemChars.push(options);
                    cnt++;
                    if (!isSymbol) {
                        poemBodyCharIndexArr.push(poemBodyCharFromIndex);
                    }
                    poemBodyCharFromIndex++;
                });
            });

            const randNum = 10;
            this.poemCharNum = poemChars.length;
            const abArr = this.disorderChars(randNum, poemBodyCharIndexArr);
            const uuidMap = {};
            for (let i = 0; i < randNum; i++) {
                const abItem = abArr[i];
                const iA = abItem['a'];
                const iB = abItem['b'];
                const pcDataA = poemChars[iA];
                const pcDataB = poemChars[iB];
                pcDataA['char'] = pcDataB['home'];
                const uuid = pcDataA['uuid'];
                uuidMap[uuid] = pcDataA['i'];
            }
            this.uuidMap = uuidMap;
            this.poemChars = poemChars;
            poemChars.map((o) => {
                this.drawCharWithBox(o);
            });
        }
        this.getScore();
        this.drawSettingBtn();
        drawBackBtn(this, Dispatcher.showPoemList);
    }

    private disorderChars(num, indexArr) {
        const arr = [];
        const abArr = [];
        if (num > 1 && Array.isArray(indexArr)) {
            if (num > indexArr) {
                num = indexArr.length;
            }
            let cnt = 0;
            while (arr.length < num) {
                const maxIdx = indexArr.length - 1;
                const randIdx = randomNum(maxIdx);
                const idx = indexArr[randIdx];
                arr.push(idx);
                indexArr.splice(randIdx, 1);
                if (cnt > 0) {
                    abArr.push({
                        a: idx,
                        b: arr[cnt - 1]
                    });
                }
                cnt++;
                if (cnt >= 100) {
                    break;
                }
            }
            abArr.push({
                a: arr[0],
                b: arr[cnt - 1]
            });
        }
        return abArr;
    }

    private drawTitle(options) {
        const {title, size, boxW} = options;
        const text = new egret.TextField();
        text.text = title;
        text.fontFamily = FontFamilyPoem;
        text.textColor = ColorWhite;
        text.size = size;
        text.multiline = true;
        text.bold = true;
        this.titleRealW = text.width;
        text.width = boxW;
        const fromX = 2 * SizePw;
        text.x = fromX;
        text.textAlign = 'center';
        this.titleH = text.height;
        this.titleFromX = fromX;
        // this.addChildAt(text, this.numChildren);
        return text;
    }

    private drawCharWithBox(options) {
        const {uuidMap, poemChars} = this;
        const {uuid, home, char, size, x, y, boxX, boxY, boxW, boxH, boxBorderRadius} = options;
        let label = new Char();
        let inHome = false;
        if (home === char) {
            inHome = true;
        }
        label.textColor = ColorWhite;
        label.text = char;
        label.fontFamily = '"隶书","Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB"';
        label.size = size;
        const charHalfW = label.textWidth / 2;
        const charHalfH = label.textHeight / 2;
        const charX = x - charHalfW;
        label.x = charX;
        const charY = y - charHalfH;
        label.y = charY;
        label.uuid = uuid;
        const mi = uuidMap[uuid];
        const moveAble = mi >= 0;
        const charBox = new egret.Shape();
        charBox.graphics.beginFill(ColorWhite, 0.3);
        if (moveAble) {
            if (inHome) {
                charBox.graphics.lineStyle(2, ColorGreen);
            } else {
                charBox.graphics.lineStyle(2, ColorRed);
            }
        }
        charBox.graphics.drawRoundRect(boxX, boxY, boxW, boxH, boxBorderRadius, boxBorderRadius);
        charBox.graphics.endFill();
        if (moveAble) {
            // label.touchEnabled = true;
            // label.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.touchBegin, this);
            // label.addEventListener(egret.TouchEvent.TOUCH_END, this.touchEnd, this);
            // label.addEventListener(egret.TouchEvent.TOUCH_RELEASE_OUTSIDE, this.touchEnd, this);
            const md = poemChars[mi];
            md['charX'] = charX;
            md['charY'] = charY;
            md['boxHandle'] = charBox;
            md['handle'] = label;
            md['xl'] = boxX - 5;
            md['xr'] = boxX + boxW + 5;
            md['yt'] = boxY - 5;
            md['yb'] = boxY + boxH + 5;
            // const layer = new egret.Shape();
            // layer.graphics.beginFill(0x333333, 0.5);
            // layer.graphics.drawRect(md['xl'], md['yt'], boxW + 10, boxH + 10);
            // layer.graphics.endFill();
            // mainGroup.addChildAt(layer, 1);
        }
        this.addChildAt(charBox, this.numChildren);
        this.addChildAt(label, this.numChildren + 1000);
    }

    private getHitOne(mx: number, my: number) {
        let hitOne = null;
        const {uuidMap, poemChars} = this;
        for (let k in uuidMap) {
            const n = uuidMap[k];
            const hd = poemChars[n];
            const isInX = mx >= hd['xl'] && mx <= hd['xr'];
            const isInY = my >= hd['yt'] && my <= hd['yb'];
            if (isInX && isInY) {
                hitOne = hd;
                break;
            }
        }
        return hitOne;
    }

    private draggingOne: egret.DisplayObject;
    private touchFromX = 0;
    private touchFromY = 0;

    private touchBegin(evt: egret.TouchEvent) {
        const {dragging} = this;
        if (dragging !== true) {
            const hitOne = this.getHitOne(evt.stageX, evt.stageY);
            if (hitOne) {
                this.dragging = true;
                const target = hitOne['handle'];
                target['x'] = evt.stageX - target['textWidth'] / 2;
                target['y'] = evt.stageY - target['textHeight'];
                this.draggingOne = target;
                // this.setChildIndex(hitOne, this.numChildren + 1000);
                this.addEventListener(egret.TouchEvent.TOUCH_MOVE, this.touchMove, this);
            } else {
                this.touchFromX = evt.stageX;
                this.touchFromY = evt.stageY;
            }
        }
    }

    private touchMove(evt: egret.TouchEvent) {
        if (this.dragging === true) {
            const target = this.draggingOne;
            if (target) {
                target['x'] = evt.stageX - target['textWidth'] / 2;
                target['y'] = evt.stageY - target['textHeight'];
            }
        }
    }

    private touchEnd(evt: egret.TouchEvent) {
        this.dragging = false;
        const target = this.draggingOne;
        const mx = evt.stageX;
        const my = evt.stageY;
        if (target) {
            this.removeEventListener(egret.TouchEvent.TOUCH_MOVE, this.touchMove, this);
            const tUuid = target['uuid'];
            const {uuidMap, poemChars} = this;
            const hitOne = this.getHitOne(mx, my);
            const ti = uuidMap[tUuid];
            const touchOne = poemChars[ti];
            const tx = touchOne['charX'];
            const ty = touchOne['charY'];
            if (hitOne) {
                const {i: hi, uuid: hUuid, charX: hx, charY: hy, char: hChar, handle: hHandle} = hitOne;
                if (hi === ti) {
                    target['x'] = tx;
                    target['y'] = ty;
                } else {
                    const tChar = touchOne['char'];
                    target['x'] = hx;
                    target['y'] = hy;
                    hHandle['x'] = tx;
                    hHandle['y'] = ty;
                    touchOne['char'] = hChar;
                    hitOne['char'] = tChar;
                    touchOne['handle'] = hHandle;
                    hitOne['handle'] = target;
                    target['uuid'] = hUuid;
                    hHandle.uuid = tUuid;
                    this.handleCharStatus(touchOne);
                    this.handleCharStatus(hitOne);
                    this.getScore();
                }
            } else {
                target['x'] = tx;
                target['y'] = ty;
            }
            this.draggingOne = null;
            // this.setChildIndex(target, 1000);
        } else {
            const xLen = this.touchFromX - mx;
            const yLen = this.touchFromY - my;
            const ixLen = Math.abs(xLen);
            const iyLen = Math.abs(yLen);
            const minLen = 100;
            if (ixLen >= minLen) {
                const deg = getTanDeg(iyLen, ixLen);
                if (deg <= 30) {
                    const {index, poemList} = this;
                    if (xLen > 0) {
                        // 向后
                        const total = poemList.length;
                        if (index === total - 1) {
                            Dispatcher.showPoemList();
                        } else {
                            Dispatcher.showPoem(index + 1);
                        }
                    } else {
                        // 向前
                        if (index > 0) {
                            Dispatcher.showPoem(index - 1);
                        } else {
                            Dispatcher.showPoemList();
                        }
                    }
                }
            }
        }
        this.touchFromX = 0;
        this.touchFromY = 0;
    }

    private getScore() {
        const {uuidMap, poemChars} = this;
        let cnt = 0;
        let total = 0;
        for (let uuid in uuidMap) {
            total++;
            const n = uuidMap[uuid];
            const item = poemChars[n];
            if (item['home'] === item['char']) {
                cnt++;
            }
        }
        let score = 0;
        if (total > 0) {
            score = Math.ceil((100 / total) * cnt);
            if (score > 100) {
                score = 100;
            }
        }
        this.drawScoreBoard(score);
    }

    private drawScoreBoard(score) {
        const {stageW, scoreBoardH} = this;
        let tScore: egret.TextField = this.textScoreHandler;
        const boardW = 200;
        if (!tScore) {
            tScore = new egret.TextField();
            tScore.width = boardW;
            tScore.height = scoreBoardH;
            tScore.fontFamily = '"Comic Sans MS","Comic Sans",cursive';
            tScore.size = 60;
            tScore.y = this.scoreBoardFromY;
            tScore.textColor = ColorYellow;
            tScore.strokeColor = 0x000000;
            tScore.stroke = 2;
            tScore.italic = true;
            tScore.bold = true;
            tScore.textAlign = egret.HorizontalAlign.CENTER;
            tScore.verticalAlign = egret.VerticalAlign.MIDDLE;
            this.textScoreHandler = tScore;
            this.addChild(tScore);
        }
        tScore.text = score;
        tScore.x = (stageW - boardW) / 2 + SizePw;
    }

    private handleCharStatus(item: object) {
        const char = item['char'];
        const home = item['home'];
        const charBox = item['boxHandle'];
        const boxX = item['boxX'];
        const boxY = item['boxY'];
        const boxW = item['boxW'];
        const boxH = item['boxH'];
        const boxBorderRadius = item['boxBorderRadius'];
        charBox.graphics.clear();
        if (char === home) {
            charBox.graphics.beginFill(ColorWhite, 0.3);
            charBox.graphics.lineStyle(2, ColorGreen);
        } else {
            charBox.graphics.beginFill(ColorWhite, 0.3);
            charBox.graphics.lineStyle(2, ColorRed);
        }
        charBox.graphics.drawRoundRect(boxX, boxY, boxW, boxH, boxBorderRadius, boxBorderRadius);
        charBox.graphics.endFill();
    }

    private drawSettingBtn(): void {
        const {stageW, stageH} = this;
        const btnSetting = createBitmapByName("button_setting_png");
        const btnW = 48;
        const btnH = 48;
        btnSetting.width = btnW;
        btnSetting.height = btnH;
        btnSetting.anchorOffsetX = btnW / 2;
        btnSetting.anchorOffsetY = btnH / 2;
        btnSetting.x = stageW - 2 * SizePw - btnW / 2;
        btnSetting.y = stageH - 2 * SizePh - btnH / 2;
        btnSetting.touchEnabled = true;
        this.addChild(btnSetting);
        btnSetting.addEventListener(egret.TouchEvent.TOUCH_BEGIN, (evt: egret.TouchEvent) => {
            evt.currentTarget.rotation = 90;
        }, this);
        btnSetting.addEventListener(egret.TouchEvent.TOUCH_END, (evt: egret.TouchEvent) => {
            evt.currentTarget.rotation = 0;
        }, this);
    };
}
